#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "GCCMakros.h"
#include "Scanner.h"

#define CLASSCONST      1
#define CLASSVAR        2
#define CLASSTYPE       3
#define CLASSFUNC       4
#define CLASSARRAY      5

#define FORMINT         1
#define FORMBOOL        2
#define FORMCHAR        3
#define FORMVOID        4
#define FORMARRAY       5
#define FORMSTRUCT      6
#define FORMFUNC        7

#define SCOPEGLOBAL     1
#define SCOPELOCAL      2
#define SCOPEFIELD      3

typedef struct Type ptr type_t;
typedef struct Object ptr object_t;
typedef struct SymTab ptr symTab_t;


symTab_t bottom;
symTab_t top;
int height;

/* Symbol Table */
struct SymTab
{
    object_t head;
    object_t tail;
    symTab_t lower;
    int length;
};

struct Object
{
    string_t          name;
    int               oClass;
    type_t            type;
    object_t          next;
    int               val;
    int               scope;
    int               offset;
};

struct Type
{
    int               form;         /* the DataType */
    int               len;          /* length only for arrays */
    int               size;         /* maybe for address calculation */
    symTab_t          fields;       /* the fields of a struct */
    type_t            base;         /* the baseType of a Array */
};

/* the basic Types */
type_t intType;
type_t boolType;
type_t charType;
type_t voidType;

/* Stack functions */
void initSymTabStack();
void push(symTab_t symTab);
object_t search(string_t name);
object_t searchProcedure(string_t name);
void pop();
void clearSymTabStack();
void newObj(object_t obj);
void newStage();
void printSymTabStack();

/* SymTab Functions */
void initSubSymTab(symTab_t symTab);
void initSymTab(symTab_t symTab);
void add(symTab_t symTab,
         string_t   name,
         int        oClass,
         type_t     Type,
         int        val);
void addObj(symTab_t symTab, object_t node);
void printSymTable();
void printObj(object_t object);
object_t getByName(symTab_t symTab, string_t name);
int calcSize(symTab_t symTab);
void deleteByName(symTab_t symTab, string_t name);
void deleteList(symTab_t symTab);
void printType(type_t type);
